package com.nc.delivery_project.server.db_util;

import org.apache.commons.dbcp.BasicDataSource;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Created by miroshnik on 22.12.2014.
 * 
 * Database connection pool 
 */
public final class ConnectionManager {

    public final static String DB_ACCESS_PROPERTIES_PATH = "com/nc/delivery_project/db_access.property";

    private static final String PROPERTY_DRIVER = "driver";
    private static final String PROPERTY_URL = "url";
    private static final String PROPERTY_USER = "user";
    private static final String PROPERTY_PASS = "pass";
    public static final int MAX_IDLE = 30;
    public static final int MAX_WAIT = 10000;
    public static final int MAX_ACTIVE = 100;
    public static final int MAX_OPEN_STATEMENTS = 180;
    public static final boolean REMOVE_ABANDONED = true;
    public static final int REMOVE_ABANDONED_TIMEOUT = 30;
    public static final boolean LOG_ABANDONED = true;

    private BasicDataSource dataSource;
    
    private static volatile ConnectionManager connectionManager;

    private ConnectionManager(){
        Properties dbProperties = loadDbProperties(DB_ACCESS_PROPERTIES_PATH);

        dataSource = new BasicDataSource();

        dataSource.setDriverClassName(dbProperties.getProperty(PROPERTY_DRIVER));
        dataSource.setUsername(dbProperties.getProperty(PROPERTY_USER));
        dataSource.setPassword(dbProperties.getProperty(PROPERTY_PASS));
        dataSource.setUrl(dbProperties.getProperty(PROPERTY_URL));

        dataSource.setMaxIdle(MAX_IDLE);
        dataSource.setMaxWait(MAX_WAIT);
        dataSource.setMaxActive(MAX_ACTIVE);
        dataSource.setMaxOpenPreparedStatements(MAX_OPEN_STATEMENTS);

        //автоматически возвращает в пул соединения, которые не были закрыты а ссылка на connection потеряна
        dataSource.setRemoveAbandoned(REMOVE_ABANDONED);
        dataSource.setRemoveAbandonedTimeout(REMOVE_ABANDONED_TIMEOUT);
        dataSource.setLogAbandoned(LOG_ABANDONED);
    }

    /**
     * Get ConnectionManager what consist connection pool* 
     * @return ConnectionManager
     */
    public static ConnectionManager getInstance() {
        if (connectionManager == null) {
            synchronized (ConnectionManager.class) {
                if (connectionManager == null) {
                    connectionManager = new ConnectionManager();
                }
            }
        }

        return connectionManager;
    }

    /**
     * Get one of pooled DB connection
     * @return DB connection
     * @throws SQLException
     */
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    
    private Properties loadDbProperties(String path) {
        Properties prop = new Properties();
        
        try {
            prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(path));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return prop;
    }
}
